#include <iostream>
#include <ostream>
#include <cstring>

using namespace std;

// 异常类
class OutOfRange {
	public:
		OutOfRange() : m_flag(1) {}
		OutOfRange(int len, int index) : m_len(len), m_index(index), m_flag(2) {}
		void what()const;
	private:
		int m_len; // 数组的长度
		int m_index; // 访问的数组下标
		int m_flag; // m_flag == 1 数组空 m_flag == 2数组越界
};

void OutOfRange::what()const
{
	if (1 == m_flag) {
		cout << "empty array" << endl;
	} else if (2 == m_flag) {
		cout << "array index:0~" << m_len - 1 << ", but your index is " << m_index << "! out of range" << endl;
	} else {
		cout << "unknow exception!" << endl;
	}
}

template <typename T>
class Arr {
	public:
		Arr(int s = 0);
		// 深拷贝 拷贝构造方法
		Arr(const Arr &a);
		~Arr();
		void push_back(T value);

		// 重载运算符
		T &operator[](int i);
		const T &operator[](int i) const;

		Arr &operator=(const Arr &a);
		template <typename TP>
		friend ostream &operator<< (ostream &out, Arr<TP> &a);

	private:
		T *m_p; // 起始地址
		int m_size; // 容量
};

template <typename T>
Arr<T>::Arr(int s) : m_size(s)
{
	if (0 == s) {
		m_p = NULL;
		return;
	}
	m_p = new T[m_size];
}

template <typename T>
Arr<T>::Arr(const Arr &a)
{
	if (a.m_p == NULL) {
		this->m_p = NULL;
		this->m_size = 0;
		return;
	}

	if (this == &a) {
		// 防止用自己赋值 obj = obj
		return;
	}
	this->m_p = new T[a.m_size];
	this->m_size = a.m_size;
	memcpy(this->m_p, a.m_p, sizeof(T) * m_size);
}

template <typename T>
Arr<T>::~Arr()
{
	cout << "delete" << endl;
	if (m_p) {
		delete [] m_p;
		m_p = NULL;
	}
}

template <typename T>
T & Arr<T>::operator[](int i)
{
	if (i < 0 || i >= m_size) {
		// 抛出异常对象
		throw OutOfRange(m_size, i);
	}
	return m_p[i];
}

template <typename T>
const T & Arr<T>::operator[](int i)const
{
	if (i < 0 || i >= m_size) {
		// 抛出异常对象
		throw OutOfRange(m_size, i);
	}
	return m_p[i];
}

template <typename T>
Arr<T> & Arr<T>::operator=(const Arr &a)
{
	cout << "operator=调用了" << endl;
	// a, b都是Arr对象 b = a this指向b a就是参数	
	if (this->m_p) {
		delete[] this->m_p;
	}
	this->m_p = new T[a.m_size];
	this->m_size = a.m_size;
	memcpy(this->m_p, a.m_p, this->m_size * sizeof(T));

	return *this;
}

template <typename T>
void Arr<T>::push_back(T value)
{
	T *tmp = NULL;
	tmp = new T[m_size + 1];
	memcpy(tmp, m_p, m_size * sizeof(T));
	delete[] m_p;
	m_p = tmp;
	m_p[m_size] = value;
	m_size++;
}

template <typename T>
ostream &operator<< (ostream &out, Arr<T> &a)
{
	int i;
	for (i = 0; i < a.m_size; i++)
		out << (a.m_p)[i] << " ";
	cout << endl;

	return out;
}

int main(void)
{
	Arr<int> a1(10);
	Arr<int> a2; // 空的
	int i;

	for (i = 0; i < 10; i++)
		a1[i] = i + 1;

	cout << a1 << endl;

	try {
		// 可能异常的代码
		i = a1[100];
	} catch (OutOfRange &e) {
		e.what();
	}

	a2 = a1;
	a2.push_back(100);
	a2.push_back(200);
	cout << a2 << endl;

	return 0;
}

